{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# 面向对象三大特性\n",
    "# 1 封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中\n",
    "# 2 继承 实现代码的重用，相同的代码不需要重复的编写\n",
    "# 3 多态 不同的对象调用相同的方法，产生不同的执行结果，增加代码的灵活"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 1.单继承"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 1.1 继承的概念、语法和特点"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 继承的概念：子类 拥有 父类 的所有 方法 和 属性"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "source": [
    "# 1) 继承的语法\n",
    "# class 类名(父类名):\n",
    "# pass\n",
    "# • 子类 继承自 父类，可以直接 享受 父类中已经封装好的方法，不需要再次开发\n",
    "# • 子类 中应该根据 职责，封装 子类特有的 属性和方法\n",
    "# 2) 专业术语\n",
    "# • Dog 类是 Animal 类的子类，Animal 类是 Dog 类的父类，Dog 类从 Animal 类继承\n",
    "# • Dog 类是 Animal 类的派生类，Animal 类是 Dog 类的基类，Dog 类从 Animal 类派生\n",
    "# 3) 继承的传递性\n",
    "# • C 类从 B 类继承，B 类又从 A 类继承\n",
    "# • 那么 C 类就具有 B 类和 A 类的所有属性和方法子类 拥有 父类 以及 父类的父类 中封装的所有 属性 和 方法,不继承时后不需要加括号"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "execution_count": null,
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "吃---\n",
      "喝---\n",
      "跑---\n",
      "睡---\n",
      "汪汪叫\n"
     ]
    }
   ],
   "source": [
    "class Animal:\n",
    "    def eat(self):\n",
    "        print(\"吃---\")\n",
    "    def drink(self):\n",
    "        print(\"喝---\")\n",
    "    def run(self):\n",
    "        print(\"跑---\")\n",
    "    def sleep(self):\n",
    "        print(\"睡---\")\n",
    "\n",
    "\n",
    "class Dog(Animal):\n",
    "    # 子类拥有父类的所有属性和方法\n",
    "    # def eat(self):\n",
    "    # print(\"吃\")\n",
    "    #\n",
    "    # def drink(self):\n",
    "    # print(\"喝\")\n",
    "    #\n",
    "    # def run(self):\n",
    "    # print(\"跑\")\n",
    "    #\n",
    "    # def sleep(self):\n",
    "    # print(\"睡\")\n",
    "    def bark(self):\n",
    "        print(\"汪汪叫\")\n",
    "\n",
    "# 创建一个对象 - 狗对象\n",
    "wangcai = Dog()\n",
    "wangcai.eat()\n",
    "wangcai.drink()\n",
    "wangcai.run()\n",
    "wangcai.sleep()\n",
    "wangcai.bark()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 1.2 方法的重写"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# • 当 父类 的方法实现不能满足子类需求时，可以对方法进行 重写(override)\n",
    "\n",
    "# 重写 父类方法有两种情况：\n",
    "# 1 覆盖 父类的方法\n",
    "# 2 对父类方法进行 扩展\n",
    "# 1) 覆盖父类的方法\n",
    "# • 如果在开发中，父类的方法实现 和 子类的方法实现，完全不同\n",
    "# • 就可以使用 覆盖 的方式，在子类中 重新编写 父类的方法实现\n",
    "# 具体的实现方式，就相当于在 子类中 定义了一个 和父类同名的方法并且实现重写之后，在运行时，只会调用 子类中重写的方法，而不再会调用 父类封装的方法\n",
    "# 2) 对父类方法进行 扩展\n",
    "# • 如果在开发中，子类的方法实现 中 包含 父类的方法实现\n",
    "# – 父类原本封装的方法实现 是 子类方法的一部分\n",
    "# • 就可以使用 扩展 的方式\n",
    "# a) 在子类中 重写 父类的方法\n",
    "# b) 在需要的位置使用 super().父类方法 来调用父类方法的执行\n",
    "# c) 代码其他的位置针对子类的需求，编写 子类特有的代码实现\n",
    "\n",
    "# 关于 super\n",
    "# • 在 Python 中 super 是一个 特殊的类\n",
    "# • super() 就是使用 super 类创建出来的对象\n",
    "# • 最常 使用的场景就是在 重写父类方法时，调用"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "神一样的叫唤。。。\n",
      "汪汪叫\n",
      "委屈。。。\n"
     ]
    }
   ],
   "source": [
    "class Animal:\n",
    "    def eat(self):\n",
    "        print(\"吃---\")\n",
    "    def drink(self):\n",
    "        print(\"喝---\")\n",
    "    def run(self):\n",
    "        print(\"跑---\")\n",
    "    def sleep(self):\n",
    "        print(\"睡---\")\n",
    "\n",
    "\n",
    "class Dog(Animal):\n",
    "    def bark(self):\n",
    "        print(\"汪汪叫\")\n",
    "\n",
    "class XiaoTianQuan(Dog):\n",
    "    def fly(self):\n",
    "        print(\"我会飞\")\n",
    "    def bark(self):\n",
    "        # 1. 针对子类特有的需求，编写代码\n",
    "        print(\"神一样的叫唤。。。\")\n",
    "        # 2. 使用 super(). 调用原本在父类中封装的方法\n",
    "        #父亲的匿名对象\n",
    "        # 保留原有的父类方法的功能\n",
    "        super().bark()\n",
    "        print(\"委屈。。。\")\n",
    "\n",
    "xtq = XiaoTianQuan()\n",
    "# 如果子类中，重写了父类的方法\n",
    "# 在使用子类对象调用方法时，会调用子类中重写的方法\n",
    "xtq.bark()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 1.3 父类的私有属性和私有方法"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 1 子类对象 不能 在自己的方法内部，直接 访问 父类的 私有属性 或 私有方法\n",
    "# 2 子类对象 可以通过 父类 的 公有方法 间接 访问到 私有属性 或 私有方法（父类\n",
    "# 在自己的公有方法中调用私有方法）\n",
    "# • 私有属性、方法 是对象的隐私，不对外公开，外界 以及 子类 都不能直接访问\n",
    "# • 私有属性、方法 通常用于做一些内部的事情\n",
    "# 示例\n",
    "# 王道码农训练营-WWW.CSKAOYAN.COM\n",
    "# • B 的对象不能直接访问 __num2 属性\n",
    "# • B 的对象不能在 demo 方法内访问 __num2 属性\n",
    "# • B 的对象可以在 demo 方法内，调用父类的 test 方法\n",
    "# • 父类的 test 方法内部，能够访问 __num2 属性和 __test 方法\n",
    "class A:\n",
    "    def __init__(self):\n",
    "        self.num1 = 100\n",
    "        self.__num2 = 200\n",
    "    def __test(self):\n",
    "        print(\"私有方法 %d %d\" % (self.num1, self.__num2))\n",
    "class B(A):\n",
    "    def demo(self):\n",
    "    # 1. 在子类的对象方法中，不能访问父类的私有属性\n",
    "    # print(\"访问父类的私有属性 %d\" % self.__num2)\n",
    "    # 2. 在子类的对象方法中，不能调用父类的私有方法\n",
    "    # self.__test()\n",
    "    pass\n",
    "# 创建一个子类对象\n",
    "b = B()\n",
    "print(b)\n",
    "b.demo()\n",
    "# 在外界不能直接访问对象的私有属性/调用私有方法\n",
    "# print(b.__num2)\n",
    "# b.__test()\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 2.多继承"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 概念\n",
    "# • 子类 可以拥有 多个父类，并且具有 所有父类 的 属性 和 方法\n",
    "# • 例如：孩子 会继承自己 父亲 和 母亲 的 特性\n",
    "# class 子类名(父类名1，父类名2...)\n",
    "#     pass"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 继承的父类中存在同名的方法，尽量避免使用多继承"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)\n",
      "C demo\n"
     ]
    }
   ],
   "source": [
    "class A:\n",
    "    def demo(self):\n",
    "        print('A demo')\n",
    "\n",
    "    def test(self):\n",
    "        print('A test')\n",
    "\n",
    "\n",
    "class B:\n",
    "    def demo(self):\n",
    "        print('B demo')\n",
    "\n",
    "    def test(self):\n",
    "        print('B test')\n",
    "\n",
    "class C(A,B):\n",
    "    def demo(self):\n",
    "        print('C demo')\n",
    "\n",
    "# MRO 是 method resolution order，主要用于 在多继承时判断 方法、属性 的调用 路径\n",
    "print(C.__mro__)\n",
    "c=C()\n",
    "c.demo()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}